package com.zzyl.oss;

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.common.auth.CredentialsProviderFactory;
import com.aliyun.oss.common.auth.EnvironmentVariableCredentialsProvider;
import com.aliyun.oss.model.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.stereotype.Component;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * @author Administrator
 * @version 1.0
 * @description: TODO
 * @date 2025/1/6 14:52
 */
@Component
@EnableConfigurationProperties(AliyunOSSProperties.class)
public class AliyunOSSUtil {
    @Autowired
    private AliyunOSSProperties aliyunOSSProperties;

    /**
     * 文件上传
     *
     * @param in               文件输入流
     * @param originalFilename 文件原始名称
     * @return
     */
    public String upload(InputStream in, String originalFilename) throws Exception {
        String endpoint = aliyunOSSProperties.getEndpoint();
        String bucketName = aliyunOSSProperties.getBucketName();

        // 从环境变量中获取访问凭证。运行本代码示例之前，请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
        EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();

        // 填写Object完整路径，完整路径中不能包含Bucket名称，例如exampledir/exampleobject.txt。
        String lastffix = originalFilename.substring(originalFilename.lastIndexOf("."));   // .jpg
        String fileName = UUID.randomUUID().toString().replaceAll("-", "") + lastffix;

        // 2、构建文件路径
        String filePath = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy/MM/dd/"));

        String objectName = filePath + fileName;

        // 创建OSSClient实例。
        OSS ossClient = OSSClientBuilder.create()
                .endpoint(endpoint)
                .credentialsProvider(credentialsProvider)
                .build();

        try {
            // 创建PutObjectRequest对象。
            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, in);
            // 创建PutObject请求。
            ossClient.putObject(putObjectRequest);
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
        // https://cs-zzyl.oss-cn-beijing.aliyuncs.com/2025/01/06/01.jpg
        return "https://" + bucketName + "." + endpoint.split("//")[1] + "/" + objectName;
    }

    /**
     * 文件上传
     *
     * @param content          文件字节数组
     * @param originalFilename 原文件名
     * @return
     * @throws Exception
     */
    public String upload(byte[] content, String originalFilename) throws Exception {
        String endpoint = aliyunOSSProperties.getEndpoint();
        String bucketName = aliyunOSSProperties.getBucketName();

        // 从环境变量中获取访问凭证。运行本代码示例之前，请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
        EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();

        // 填写Object完整路径，完整路径中不能包含Bucket名称，例如exampledir/exampleobject.txt。
        String lastffix = originalFilename.substring(originalFilename.lastIndexOf("."));   // .jpg
        String fileName = UUID.randomUUID().toString().replaceAll("-", "") + lastffix;

        // 2、构建文件路径
        String filePath = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy/MM/dd/"));

        String objectName = filePath + fileName;

        // 创建OSSClient实例。
        OSS ossClient = OSSClientBuilder.create()
                .endpoint(endpoint)
                .credentialsProvider(credentialsProvider)
                .build();

        try {
            // 创建PutObjectRequest对象。
            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, new ByteArrayInputStream(content));

            // 创建PutObject请求。
            PutObjectResult result = ossClient.putObject(putObjectRequest);
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
        // https://cs-zzyl.oss-cn-beijing.aliyuncs.com/2025/01/06/01.jpg
        return "https://" + bucketName + "." + endpoint.split("//")[1] + "/" + objectName;
    }

    /**
     * 查询文件列表（Day11-实战）
     */
    public List<String> listFiles(String keyPrefix, int fileSize) throws Exception {
        String endpoint = aliyunOSSProperties.getEndpoint();
        String bucketName = aliyunOSSProperties.getBucketName();

        // 从环境变量中获取访问凭证。运行本代码示例之前，请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
        EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();

        // 创建OSSClient实例。
        OSS ossClient = OSSClientBuilder.create()
                .endpoint(endpoint)
                .credentialsProvider(credentialsProvider)
                .build();
        try {
            // 列举文件。
            ObjectListing objectListing = ossClient.listObjects(new ListObjectsRequest(bucketName).withPrefix(keyPrefix).withMaxKeys(fileSize));
            List<OSSObjectSummary> sums = objectListing.getObjectSummaries();
            if (sums != null && !sums.isEmpty()) {
                List<String> list = sums.stream().map(OSSObjectSummary::getKey).collect(Collectors.toList());
                return list;
            }
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
        return null;
    }

    /**
     * 分页查询文件列表（Day11-实战）
     */
    public List<String> pageListAllFiles(String keyPrefix, int pageSize) throws Exception {
        List<String> fileList = new ArrayList<>();
        String endpoint = aliyunOSSProperties.getEndpoint();
        String bucketName = aliyunOSSProperties.getBucketName();

        // 从环境变量中获取访问凭证。运行本代码示例之前，请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
        EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
        // 设置marker，例如objecttest.txt（当前页最后一个文档的objectName）。
        String nextMarker = null;

        // 创建OSSClient实例。
        OSS ossClient = OSSClientBuilder.create()
                .endpoint(endpoint)
                .credentialsProvider(credentialsProvider)
                .build();
        try {
            ObjectListing objectListing;
            do {
                objectListing = ossClient.listObjects(new ListObjectsRequest(bucketName).
                        withPrefix(keyPrefix).withMarker(nextMarker).withMaxKeys(pageSize));

                List<OSSObjectSummary> sums = objectListing.getObjectSummaries();
                if (sums != null && !sums.isEmpty()) {
                    List<String> list = sums.stream().map(OSSObjectSummary::getKey).collect(Collectors.toList());
                    fileList.addAll(list);
                }
                nextMarker = objectListing.getNextMarker();

            } while (objectListing.isTruncated());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
        return fileList;
    }

    /**
     * 删除指定对象（Day11-实战）
     */
    public void deleteFile(String objectName) throws Exception {
        String endpoint = aliyunOSSProperties.getEndpoint();
        String bucketName = aliyunOSSProperties.getBucketName();

        // 从环境变量中获取访问凭证。运行本代码示例之前，请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
        EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();

        // 创建OSSClient实例。
        OSS ossClient = OSSClientBuilder.create()
                .endpoint(endpoint)
                .credentialsProvider(credentialsProvider)
                .build();

        try {
            // 删除文件或目录。如果要删除目录，目录必须为空。
            ossClient.deleteObject(bucketName, objectName);
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }

    /**
     * 批量删除对象（Day11-实战）
     */
    public void batchDeleteFiles(List<String> objectNames) throws Exception {
        String endpoint = aliyunOSSProperties.getEndpoint();
        String bucketName = aliyunOSSProperties.getBucketName();

        // 从环境变量中获取访问凭证。运行本代码示例之前，请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
        EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();

        // 创建OSSClient实例。
        OSS ossClient = OSSClientBuilder.create()
                .endpoint(endpoint)
                .credentialsProvider(credentialsProvider)
                .build();

        try {
            // 删除文件。
            // 填写需要删除的多个文件完整路径。文件完整路径中不能包含Bucket名称。
            ossClient.deleteObjects(new DeleteObjectsRequest(bucketName).withKeys(objectNames).withEncodingType("url"));
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }

}
